package com.tanhua.dubbo.server.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import com.tanhua.dubbo.server.pojo.UserLike;
import com.tanhua.dubbo.server.vo.PageInfo;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class UserLikeApiImpl implements UserLikeApi {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public static final String LIKE_REDIS_KEY_PREFIX = "USER_LIKE_";

    public static final String NOT_LIKE_REDIS_KEY_PREFIX = "USER_NOT_LIKE_";

    /**
     * 获取喜欢数据的redis key
     *
     * @param userId
     * @return
     */
    private String getLikeRedisKey(Long userId) {
        return LIKE_REDIS_KEY_PREFIX + userId;
    }

    /**
     * 获取不喜欢数据的redis key
     *
     * @param userId
     * @return
     */
    private String getNotLikeRedisKey(Long userId) {
        return NOT_LIKE_REDIS_KEY_PREFIX + userId;
    }

    @Override
    public Boolean likeUser(Long userId, Long likeUserId) {
        //查看是否已经喜欢
        Boolean like = isLike(userId, likeUserId);
        if (like) {
            return false;
        }
        //如果没有喜欢,就添加喜欢数据user_like表中
        UserLike userLike = new UserLike();
        userLike.setId(ObjectId.get());
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setCreated(System.currentTimeMillis());
        mongoTemplate.save(userLike);
        //在Redis将喜欢的用户也添加到当前用户的记录中
        String redisKey = getLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        //查询Redis中喜欢的用户是否在不喜欢列表中
        Boolean notLike = isNotLike(userId, likeUserId);
        if (notLike) {
            //如果存在则删除该记录
            redisKey = getNotLikeRedisKey(userId);
            redisTemplate.opsForHash().delete(redisKey, hashKey);
        }
        return true;
    }

    @Override
    public Boolean notLikeUser(Long userId, Long likeUserId) {
        //查看是否已经不喜欢
        Boolean notLike = isNotLike(userId, likeUserId);
        if (notLike) {
            return false;
        }
        //在Redis将不喜欢的用户也添加到当前用户的记录中
        String redisKey = getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");

        //查询Redis中喜欢的用户是否在喜欢列表中
        Boolean like = isLike(userId, likeUserId);
        if (like) {
            //如果存在则删除该记录
            //在mongodb中删除
            Query query = Query.query(Criteria.where("userId").is(userId).and("likeUserId").is(likeUserId));
            mongoTemplate.remove(query, UserLike.class);
            //在redis中删除
            redisKey = getLikeRedisKey(userId);
            redisTemplate.opsForHash().delete(redisKey, hashKey);
        }
        return true;
    }

    @Override
    public Boolean isMutualLike(Long userId, Long likeUserId) {
        return isLike(userId, likeUserId) && isLike(likeUserId, userId);
    }

    @Override
    public List<Long> queryLikeList(Long userId) {
        //查询redis
        String redisKey = getLikeRedisKey(userId);
        Set<Object> keys = redisTemplate.opsForHash().keys(redisKey);
        if (CollUtil.isEmpty(keys)) {
            return ListUtil.empty();
        }
        List<Long> result = new ArrayList<>(keys.size());
        keys.forEach(o -> result.add(Convert.toLong(o)));
        return result;
    }

    @Override
    public List<Long> queryNotLikeList(Long userId) {
        //查询redis
        String redisKey = getNotLikeRedisKey(userId);
        Set<Object> keys = redisTemplate.opsForHash().keys(redisKey);
        if (CollUtil.isEmpty(keys)) {
            return ListUtil.empty();
        }
        List<Long> result = new ArrayList<>(keys.size());
        keys.forEach(o -> result.add(Convert.toLong(o)));
        return result;
    }

    /**
     * 查询相互喜欢数
     * 实现2种方式：第一种：查询redis，第二种：查询MongoDB
     * 建议：优先使用redis查询，其次考虑使用Mongodb
     *
     * @param userId
     * @return
     */
    @Override
    public Long queryMutualLikeCount(Long userId) {
        //我的好友列表
        List<Long> likeUserIdList = queryLikeList(userId);
        //我的好友中有多少个也喜欢我
        Long count = 0L;
        for (Long likeUserId : likeUserIdList) {
            String redisKey = getLikeRedisKey(likeUserId);
            String hashKey = String.valueOf(userId);
            Boolean alsoLike = redisTemplate.opsForHash().hasKey(redisKey, hashKey);
            if (alsoLike) {
                count++;
            }
        }
        return count;
    }

    @Override
    public Long queryLikeCount(Long userId) {
        String redisKey = getLikeRedisKey(userId);
        return redisTemplate.opsForHash().size(redisKey);
    }

    @Override
    public Long queryFanCount(Long userId) {
        //redis中无法查询,去mongodb中查询
        Query query = Query.query(Criteria.where("likeUserId").is(userId));
        return mongoTemplate.count(query, UserLike.class);
    }

    @Override
    public Boolean isLike(Long userId, Long likeUserId) {
        String redisKey = getLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        return redisTemplate.opsForHash().hasKey(redisKey, hashKey);
    }

    @Override
    public Boolean isNotLike(Long userId, Long likeUserId) {
        String redisKey = getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        return redisTemplate.opsForHash().hasKey(redisKey, hashKey);
    }

    @Override
    public PageInfo<UserLike> queryMutualLikeList(Long userId, Integer page, Integer pageSize) {
        //调用写好的方法查询我喜欢的用户
        List<Long> userIds = queryLikeList(userId);
        //根据喜欢的用户id去查也喜欢我的
        Query query = Query.query(Criteria.where("userId").in(userIds).and("likeUserId").is(userId));
        return queryList(query, page, pageSize);
    }

    @Override
    public PageInfo<UserLike> queryLikeList(Long userId, Integer page, Integer pageSize) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        return queryList(query, page, pageSize);
    }

    @Override
    public PageInfo<UserLike> queryFanList(Long userId, Integer page, Integer pageSize) {
        Query query = Query.query(Criteria.where("likeUserId").is(userId));
        return queryList(query, page, pageSize);
    }

    public PageInfo<UserLike> queryList(Query query, Integer page, Integer pageSize) {
        //设置分页
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize,
                Sort.by(Sort.Order.desc("created")));
        query.with(pageRequest);

        List<UserLike> userLikeList = mongoTemplate.find(query, UserLike.class);

        PageInfo<UserLike> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(userLikeList);

        return pageInfo;
    }
}
